package yxy.cherry.game.base.bean;

import java.util.concurrent.TimeUnit;

import org.redisson.api.RBucket;

import yxy.apple.util.RandomStringUtility;
import yxy.apple.util.redisson.RedisConnection;
import yxy.apple.util.redisson.RedisException;

public class UserBean {
//	public static final String RedisKeySharedTokenPrefix = "uc_token_";
//	public static final String RedisKeySharedInfoPrefix = "uc_info_";
	public static final String RedisKeySharedUserPrefix = "uc_user_";

	// bean===========================================================================
	private int uid;
	private int sid;
	private String pcode = "";
	private String token;

	public int getUid() {
		return uid;
	}

	public void setUid(int uid) {
		this.uid = uid;
	}

	public int getSid() {
		return sid;
	}

	public void setSid(int sid) {
		this.sid = sid;
	}

	public String getPcode() {
		return pcode;
	}

	public void setPcode(String pcode) {
		this.pcode = pcode;
	}

	public String getToken() {
		return token;
	}

	public void setToken(String token) {
		this.token = token;
	}

	public UserBean() {
		// TODO Auto-generated constructor stub
	}

	// redis==========================================================================
	private static <V> RBucket<V> touch(RedisConnection redis, String key) throws RedisException {
		if (redis.ready()) {
			try {
				return redis.client().getBucket(key);
			} catch (Exception e) {
				throw new RedisException(e);
			}
		} else {
			throw new RedisException("无可用Redis连接!");
		}
	}

	private static RBucket<UserBean> touchBean(RedisConnection redis, int uid) throws RedisException {
		if (redis.ready()) {
			try {
				RBucket<UserBean> bucket = touch(redis, RedisKeySharedUserPrefix + uid);
				return bucket;
			} catch (Exception e) {
				throw new RedisException(e);
			}
		} else {
			throw new RedisException("无可用Redis连接!");
		}
	}

	public static void update(RedisConnection redis, int uid, int sid, String pcode, int expiration) throws RedisException {
		UserBean bean = get(redis, uid);
		if (bean == null) {
			bean = new UserBean();
			bean.setUid(uid);
		}
		bean.setSid(sid);
		bean.setPcode(pcode);

		RBucket<UserBean> bucket = touchBean(redis, uid);
		bucket.set(bean);
		if (expiration > 0) {
			bucket.expire(expiration, TimeUnit.SECONDS);
		}
	}

	public static UserBean get(RedisConnection redis, int uid) throws RedisException {
		RBucket<UserBean> bucket = touchBean(redis, uid);
		return bucket.get();
	}

	/**
	 * 通过令牌验证请求有效性，不会更新令牌超时
	 *
	 * @param uid   用户uid
	 * @param token 登录令牌
	 * @return 返回玩家信息，验证失败返回null
	 * @throws MulhouseException
	 */
	public static boolean verify(RedisConnection redis, int uid, String token) throws RedisException {
		return verify(redis, uid, token, 0);
	}

	/**
	 * @param uid        用户uid
	 * @param token      登录令牌
	 * @param expiration 更新令牌过期时间，小于等于0时，不做更新处理。单位秒
	 * @return 返回玩家信息，验证失败返回null
	 * @throws MulhouseException
	 */
	public static boolean verify(RedisConnection redis, int uid, String token, int expiration) throws RedisException {
		if (uid == 0 || token == null) {
			return false;
		}
		RBucket<UserBean> bucket = touchBean(redis, uid);
		if (!bucket.isExists()) {
			return false;
		}
		UserBean bean = bucket.get();
		String tk = bean.getToken();
		if (tk != null && tk.equals(token)) {
			if (expiration > 0) {
				bucket.expire(expiration, TimeUnit.SECONDS);
			}
			return true;
		} else {
			return false;
		}
	}

	/** 注册token */
	public static String sign(RedisConnection redis, int uid, int expiration) throws RedisException {
		RBucket<UserBean> bucket = touchBean(redis, uid);
		String token = RandomStringUtility.randomAlphaNumeric(32);
		if (bucket.isExists()) {
			token = bucket.get().getToken();
		} else {
			UserBean bean = new UserBean();
			bean.setUid(uid);
			bean.setToken(token);
			bucket.set(bean);
		}
		if (expiration > 0) {
			bucket.expire(expiration, TimeUnit.SECONDS);
		}
		return token;
	}

	public static boolean logout(RedisConnection redis, int uid) throws RedisException {
		RBucket<UserBean> bucket = touchBean(redis, uid);
		if (bucket.isExists()) {
			return bucket.delete();
		}
		return false;
	}

}
